package net.maku.member.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.AllArgsConstructor;
import net.maku.framework.common.exception.ErrorCode;
import net.maku.framework.common.exception.ServerException;
import net.maku.framework.mybatis.service.impl.BaseServiceImpl;
import net.maku.framework.security.cache.TokenStoreCache;
import net.maku.framework.security.properties.SecurityProperties;
import net.maku.framework.security.user.UserDetail;
import net.maku.framework.security.utils.TokenUtils;
import net.maku.member.dao.MemberUserDao;
import net.maku.member.dao.MemberUserTokenDao;
import net.maku.member.entity.MemberUserEntity;
import net.maku.member.entity.MemberUserTokenEntity;
import net.maku.member.service.MemberUserTokenService;
import net.maku.member.vo.MemberUserTokenVO;
import net.maku.system.convert.SysUserConvert;
import net.maku.system.convert.SysUserTokenConvert;
import net.maku.system.entity.SysUserEntity;
import net.maku.system.entity.SysUserTokenEntity;
import net.maku.system.service.SysUserDetailsService;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;

/**
 * @Author: qr
 * @Date: 2025/3/24 23:17
 * @Version 1.0
 */
@Service
@AllArgsConstructor
public class MemberUserTokenServiceImpl extends BaseServiceImpl<MemberUserTokenDao, MemberUserTokenEntity> implements MemberUserTokenService {
    private final TokenStoreCache tokenStoreCache;
    private final SysUserDetailsService sysUserDetailsService;
    private final SecurityProperties securityProperties;
    private final MemberUserDao memberUserDao;

    @Override
    public MemberUserTokenVO createToken(Long userId) {
        // 生成token
        String accessToken = TokenUtils.generator();
        String refreshToken = TokenUtils.generator();

        MemberUserTokenEntity entity = new MemberUserTokenEntity();
        entity.setUserId(userId);
        entity.setAccessToken(accessToken);
        entity.setRefreshToken(refreshToken);

        // 过期时间
        Date now = new Date();
        entity.setAccessTokenExpire(DateUtil.toLocalDateTime(DateUtil.offsetSecond(now, securityProperties.getAccessTokenExpire())));
        entity.setRefreshTokenExpire(DateUtil.toLocalDateTime(DateUtil.offsetSecond(now, securityProperties.getRefreshTokenExpire())));

        // 是否存在Token
        MemberUserTokenEntity tokenEntity = baseMapper.selectOne(new LambdaQueryWrapper<MemberUserTokenEntity>().eq(MemberUserTokenEntity::getUserId, userId));
        if (tokenEntity == null) {
            baseMapper.insert(entity);
        } else {
            entity.setId(tokenEntity.getId());
            baseMapper.updateById(entity);
        }

        return BeanUtil.copyProperties(entity, MemberUserTokenVO.class);
    }

    @Override
    public MemberUserTokenVO refreshToken(String refreshToken) {
        LambdaQueryWrapper<MemberUserTokenEntity> query = Wrappers.lambdaQuery();
        query.eq(MemberUserTokenEntity::getRefreshToken, refreshToken);
        query.ge(MemberUserTokenEntity::getRefreshTokenExpire, new Date());

        // 不存在，则表示refreshToken错误，或者已过期
        MemberUserTokenEntity entity = baseMapper.selectOne(query);
        if (entity == null) {
            throw new ServerException(ErrorCode.REFRESH_TOKEN_INVALID);
        }

        // 删除缓存信息
        tokenStoreCache.deleteUser(entity.getAccessToken());

        // 生成新 accessToken
        String accessToken = TokenUtils.generator();
        entity.setAccessToken(accessToken);
        entity.setAccessTokenExpire(DateUtil.toLocalDateTime(DateUtil.offsetSecond(new Date(), securityProperties.getAccessTokenExpire())));

        // 更新
        baseMapper.updateById(entity);

        // 设置用户权限信息
        MemberUserEntity user = memberUserDao.selectById(entity.getUserId());
        UserDetail userDetail = BeanUtil.copyProperties(user, UserDetail.class);
        sysUserDetailsService.getUserDetails(userDetail);

        // 保存用户信息到缓存
        tokenStoreCache.saveUser(accessToken, userDetail);

        return BeanUtil.copyProperties(entity, MemberUserTokenVO.class);
    }

    @Override
    public void expireToken(Long userId) {
        MemberUserTokenEntity entity = new MemberUserTokenEntity();
        LocalDateTime now = LocalDateTime.now();
        entity.setAccessTokenExpire(now);
        entity.setRefreshTokenExpire(now);

        baseMapper.update(entity, new LambdaQueryWrapper<MemberUserTokenEntity>().eq(MemberUserTokenEntity::getUserId, userId));
    }

}
